package com.glc.lpp.simulation;

import com.baomidou.framework.common.util.DateUtil;
import com.glc.lpp.simulation.res.Equipment;
import com.glc.lpp.simulation.res.Operator;
import com.glc.lpp.simulation.res.WorkSpace;
import com.glc.lpp.simulation.workstation.*;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 仓储仿真入口
 *
 * @author xin.luo
 * @version V1.0
 * @since 2017/5/11 11:21
 */
public class SimuMain {

    private ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);
    private DecimalFormat df = new DecimalFormat("##.##");
    private List<WorkStation> stations; //工作台
    private Map<String, List<Number>> snapshotMap = new LinkedHashMap<String, List<Number>>();
    private Date minTime;

    public SimuMain(Date minTime) {
        stations = new ArrayList<WorkStation>();
        this.minTime = minTime;
    }

    //添加工作台
    public void addWorkStation(WorkStation station) {
        stations.add(station);
    }

    public void simulate() {
        final AtomicInteger timeLine = new AtomicInteger();
        List<WorkStation> radomStaions = new ArrayList<WorkStation>(stations);
        long start = System.currentTimeMillis();
        while (true) {
            int current = timeLine.addAndGet(1);
            if (!isWorking()) {
                print(current);
                break;
            }
            for (WorkStation station : radomStaions) {
                station.receiveGoods(current);
            }
            print(current);
            Collections.shuffle(radomStaions);
            final CountDownLatch latch = new CountDownLatch(radomStaions.size());
            for (final WorkStation station : radomStaions) {
                pool.execute(new Runnable() {
                    @Override
                    public void run() {
                        station.start(timeLine.get());
                        station.end(timeLine.get());
                        latch.countDown();
                    }
                });
            }
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        pool.shutdown();
        System.out.println("仿真模拟结束。。。耗时：" + (System.currentTimeMillis() - start));
    }

    public void print(int timeLine) {
        List<Number> snapshot = new ArrayList<Number>();
        for (WorkStation station : stations) {
            snapshot.add(station.waitQueue);
            snapshot.add(station.operator.getAvailable());
            if (station.operator.originalAvailable > 0) {
                snapshot.add((station.operator.originalAvailable - station.operator.getAvailable()) * 100.0d / station.operator.originalAvailable);
            } else {
                snapshot.add(0d);
            }
            snapshot.add(station.equip.getAvailable());
            if (station.equip.originalAvailable > 0) {
                snapshot.add((station.equip.originalAvailable - station.equip.getAvailable()) * 100.0d / station.equip.originalAvailable);
            } else {
                snapshot.add(0d);
            }
        }
//        System.out.print(timeLine + ":");
//        for(Number n : snapshot){
//            System.out.print(n + ",");
//        }
//        System.out.println();
        snapshotMap.put(DateUtil.format(DateUtil.addSeconds(minTime, timeLine), "yyyy-MM-dd HH:mm:ss"), snapshot);
    }

    //判断模拟是否还在继续
    private boolean isWorking() {
        for (WorkStation station : stations) {
            if (station.working()) {
                return true;
            }
        }
        return false;
    }

    public Map<String, List<Number>> getSnapshotMap() {
        return snapshotMap;
    }

    public static void main(String[] args) {
        int timeLine = 1;//时间线
        Map<Integer, Integer> goodsMapIn = new HashMap<Integer, Integer>();
        Map<Integer, Integer> goodsMapOut = new HashMap<Integer, Integer>();
        Random random = new Random(47);
        for (int i = 0; i < 10; i++) {
            goodsMapIn.put(random.nextInt(10) + 10, random.nextInt(1000000));
            goodsMapOut.put(random.nextInt(10) + 10, random.nextInt(100000));
        }
        int queueInSize = goodsMapIn.size();
        int queueOutSize = goodsMapOut.size();
        int total = 0;
        for (Integer value : goodsMapIn.values()) {
            total += value;
        }
        for (Integer value : goodsMapOut.values()) {
            total += value;
        }
        final long start = System.currentTimeMillis();
        Operator upload_oper = new Operator("卸货员", 11, 5);
        Operator inspect_oper = new Operator("检验员", 2, 1);
        Operator store_oper = new Operator("上架员", 21, 2);
        Operator pickup_oper = new Operator("分拣员", 11, 5);
        Operator package_oper = new Operator("包装员", 7, 15);
        Operator recheck_oper = new Operator("复核员", 5, 1);
        Operator out_oper = new Operator("出库员", 11, 2);

        Equipment equ1 = new Equipment("木质托盘", 10000, 100);
        Equipment equ2 = new Equipment("电叉车", 15, 10);
        Equipment equ3 = new Equipment("捡货车", 5, 10);
        WorkSpace upload_space = new WorkSpace("卸货区", 100);
        WorkSpace inspect_space = new WorkSpace("检验区", 10);
        WorkSpace store_space = new WorkSpace("上架区", 100);
        WorkSpace pickup_space = new WorkSpace("分拣区", 100);
        WorkSpace package_space = new WorkSpace("包装区", 100);
        WorkSpace recheck_space = new WorkSpace("复核区", 100);
        WorkSpace out_space = new WorkSpace("出库区", 100);
        WorkStation unload = new WorkStation(upload_oper, equ2, upload_space);
        WorkStation inspect = new WorkStation(inspect_oper,Equipment.NULL, inspect_space);
        WorkStation store = new WorkStation(store_oper, equ2, store_space);
        unload.setGoodsMap(goodsMapIn);
        unload.setNextWorkStation(inspect);
        inspect.setNextWorkStation(store);
        WorkStation pickup = new WorkStation(pickup_oper, equ3, pickup_space);
        WorkStation pack = new WorkStation(package_oper,Equipment.NULL, package_space);
        WorkStation recheck = new WorkStation(recheck_oper, Equipment.NULL,recheck_space);
        WorkStation out = new WorkStation(out_oper, equ2, out_space);
        pickup.setGoodsMap(goodsMapOut);
        pickup.setNextWorkStation(pack);
        pack.setNextWorkStation(recheck);
        recheck.setNextWorkStation(out);
        SimuMain main = new SimuMain(new Date());
        main.addWorkStation(unload);
        main.addWorkStation(inspect);
        main.addWorkStation(store);
        main.addWorkStation(pickup);
        main.addWorkStation(pack);
        main.addWorkStation(recheck);
        main.addWorkStation(out);
        main.simulate();
        Map<String, List<Number>> snapshotMap = main.getSnapshotMap();
        System.out.println("到货列表：" + (queueInSize+queueOutSize) + "条,托盘数：" + total + "个，合计处理时间：" + (System.currentTimeMillis() - start) + "秒");

      Object time =   snapshotMap.keySet().toArray()[snapshotMap.size()-1];
        System.out.println(time);
//        for (Map.Entry<String, List<Number>> entry : snapshotMap.entrySet()) {
//            System.out.print(entry.getKey() + "S,");
//            for (Number n : entry.getValue()) {
//                System.out.print(n + ",");
//            }
//            System.out.println();
//        }
//        System.out.println("到货列表：" + (queueInSize+queueOutSize) + "条,托盘数：" + total + "个，合计处理时间：" + (System.currentTimeMillis() - start) + "秒");
    }
}
